<template>
  <div class="page-search">
    <div class="page-search__search" v-if="!internalOptions.searchDisabled">
      <van-search
          v-model="internalOptions.searchKeyword.value"
          v-bind="internalOptions.searchKeyword.attribute"
          v-on="internalOptions.searchKeyword.event"
          @search="resetPageSearch"
          @clear="resetPageSearch"
      />

      <van-dropdown-menu
          v-if="!internalOptions.searchSift.disabled"
          ref="dropdownMenuRef"
          v-bind="internalOptions.searchSift.dropdownMenu.attribute"
          v-on="internalOptions.searchSift.dropdownMenu.event"
      >
        <van-dropdown-item
            v-bind="internalOptions.searchSift.dropdownItem.attribute"
            v-on="internalOptions.searchSift.dropdownItem.event"
        >
          <slot name="sift-items">
            <SearchSiftItem
                v-for="(item, index) in internalOptions.searchSiftItems"
                :key="index"
                ref="searchSiftItemsRef"
                v-bind="item"
                @change="changeSearchSiftItems"
            />
          </slot>

          <div class="sift-btn" v-if="!internalOptions.searchSift.btnDisabled">
            <van-button
                class="sift-btn__reset"
                type="default"
                @click="resetSearchSiftItems"
            >重置
            </van-button>
            <van-button
                class="sift-btn__sure"
                type="primary"
                @click="submitSearchSiftItems"
            >确定
            </van-button>
          </div>
        </van-dropdown-item>
      </van-dropdown-menu>
    </div>

    <div class="page-search__container">
      <template v-if="pageSearchData && pageSearchData.length > 0">
        <van-pull-refresh v-model="refreshing" @refresh="resetPageSearch">
          <van-list
              v-model:loading="loading"
              :finished="finished"
              :finished-text="internalOptions.finishedText"
              offset="1"
              :immediate-check="false"
              @load="submitPageSearch"
          >
            <slot>
              <template v-for="(item, index) in pageSearchData" :key="index">
                <slot :name="'list-item' + index" :row="item">
                  <component
                      v-if="internalOptions.listItemCmptName"
                      :is="internalOptions.listItemCmptName"
                      v-bind="item"
                  />

                  <div v-else class="bg-white p-3 text-sm">
                    {{ item }}
                  </div>
                </slot>
              </template>
            </slot>
          </van-list>
        </van-pull-refresh>
      </template>

      <van-empty
          v-else
          class="container__empty"
          :description="internalOptions.emptyDesc"
      />
    </div>
  </div>
</template>

<script lang="js">
import {defineComponent} from 'vue';
import _ from 'lodash';
import SearchSiftItem from './SearchSiftItem.vue';

export default defineComponent({
  name: 'ListRefreshLoad',
  components: {SearchSiftItem},
  props: {
    /**
     *  - request：向后端发送请求获取数据的请求函数，该函数的请求参数和返回值的结果需要注意
     *   - 请求参数结构
     *    - currentPage：当前页码（分页）
     *    - pageSize：每页数据数（分页）
     *    - 搜索Input键值对：搜索项键与options.searchKeyword.prop相应，值为input组件v-model双向绑定值
     *    - 搜索筛选键值对：参数配置键与options.searchSiftItems.prop相应，值与options.searchSiftItems.value相应
     *   - 返回值结构
     *    - code：响应状态码
     *    - msg：响应状态描述
     *    - data：响应数据。如分页则结构如下data{}
     *     - total：总数
     *     - rows[]：后端返回给前端的详细数据
     *  - requestAfter：请求数据完成后执行的函数，常用于外部Card获取数据，参数为当前页的所有数据
     *  - dataConfig：返回数据结构键名配置
     *   - key：详细数据键
     *   - paginationTotalKey：总条数键
     *   - paginationCurrentPageKey：当前页数键
     *  - searchDisabled：搜索栏是否禁用
     *  - searchKeyword：input搜索栏配置
     *   - prop：参数名
     *   - value：参数值
     *   - attribute：v-bind对象
     *   - event：v-on对象
     *  - searchSift：搜索栏筛选配置
     *   - disabled：筛选项是否禁用
     *   - btnDisabled：重置/确定按钮是否禁用
     *   - dropdownMenu/dropdownItem
     *    - attribute：v-bind对象
     *    - event：v-on对象
     *  - searchSiftItems[]：搜索栏筛选项配置
     *   - prop：参数名
     *   - title：搜索栏筛选项标题
     *   - siftItems[]：筛选项
     *    - label：筛选项名
     *    - value：筛选项值
     *   - isMultiple：是否多选
     *  - pagination：分页配置
     *   - pageSize：每页显示条目个数
     *   - currentPage：当前页数
     *  - emptyDesc：空提示文字
     *  - finishedText：加载结束提示文字
     *  - listItemCmptName：分页内部循环组件
     */
    options: Object
  },
  data() {
    return {
      internalOptions: {
        request() {},
        requestAfter() {},
        dataConfig: {
          key: 'rows',
          paginationTotalKey: 'total',
          paginationCurrentPageKey: 'currentPage',
        },
        searchDisabled: false,
        searchKeyword: {
          prop: 'keyword',
          value: '',
          attribute: {
            placeholder: '查询/关键字索引',
            background: 'none',
          },
          event: {}
        },
        searchSift: {
          disabled: false,
          btnDisabled: false,
          dropdownMenu: {
            attribute: {
              'close-on-click-overlay': false
            },
            event: {},
          },
          dropdownItem: {
            attribute: {
              title: '筛选'
            },
            event: {},
          },
        },
        searchSiftItems: [],
        pagination: {
          pageSize: 5,
          currentPage: 0,
        },
        emptyDesc: '暂无数据',
        finishedText: '没有更多了',
        listItemCmptName: ''
      },
      refreshing: false,
      loading: false,
      finished: false,
      total: 0,
      pageSearchData: [],
    };
  },
  computed: {
    requestParams() {
      const internalOptions = _.cloneDeep(this.internalOptions);
      const params = _.cloneDeep(internalOptions.pagination);

      if (internalOptions.searchDisabled) {
        return params;
      }

      params[internalOptions.searchKeyword.prop] = internalOptions.searchKeyword.value;

      internalOptions.searchSiftItems.forEach(item => {
        if (!item.value) {
          return;
        }

        params[item.prop] = item.value;
      });
      return params;
    }
  },
  watch: {
    'options.searchSiftItems': {
      deep: true,
      handler(newVal) {
        this.internalOptions.searchSiftItems = newVal;
      }
    }
  },
  created() {
    this.initOptions();
    this.resetPageSearch();
  },
  methods: {
    initOptions() {
      this.internalOptions = _.defaultsDeep(this.options, this.internalOptions);

      const defaultSearchSiftItem = {
        prop: '',
        title: '',
        siftItems: [],
        isMultiple: false,
      };
      this.internalOptions.searchSiftItems = this.internalOptions.searchSiftItems.map(item => _.defaultsDeep(item, defaultSearchSiftItem));
    },
    resetPageSearch() {
      this.finished = false;
      this.refreshing = false;
      this.internalOptions.pagination.currentPage = 0;
      this.pageSearchData = [];
      this.submitPageSearch();
    },
    submitPageSearch() {
      this.internalOptions.pagination.currentPage++;

      Promise.resolve(this.internalOptions.request(this.requestParams)).then((data) => {
        if (data[this.internalOptions.dataConfig.paginationCurrentPageKey] === 1) {
          this.pageSearchData = data[this.internalOptions.dataConfig.key];
        } else {
          this.pageSearchData = this.pageSearchData.concat(...data[this.internalOptions.dataConfig.key]);
        }
        this.internalOptions.requestAfter(this.pageSearchData);
        this.internalOptions.pagination.currentPage = data[this.internalOptions.dataConfig.paginationCurrentPageKey];
        this.total = data[this.internalOptions.dataConfig.paginationTotalKey];
      }).finally(() => {
        this.loading = false;
        if (this.pageSearchData.length === this.total) {
          this.finished = true;
        }
      });
    },
    changeSearchSiftItems(data) {
      const searchSiftItems = this.internalOptions.searchSiftItems;

      const findIndex = searchSiftItems.findIndex(item => item.prop === data.key);
      if (findIndex === -1) {
        return;
      }
      this.internalOptions.searchSiftItems[findIndex].value = data.res;
    },
    resetSearchSiftItems() {
      if (this.$refs.searchSiftItemsRef) {
        this.$refs.searchSiftItemsRef.forEach(item => {
          item.clearAllChoice();
        });
      }

      const searchSiftItems = this.internalOptions.searchSiftItems;
      this.internalOptions.searchSiftItems = searchSiftItems.map(item => {
        item.value = '';
        return item;
      });
      this.resetPageSearch();

      if (this.$refs.dropdownMenuRef) {
        this.$refs.dropdownMenuRef.close();
      }
    },
    submitSearchSiftItems() {
      this.resetPageSearch();
      this.$refs.dropdownMenuRef.close();
    },
  }
});
</script>

<style scoped lang="scss">
.page-search {
  display: flex;
  flex-direction: column;

  &__search {
    display: flex;
    column-gap: 20px;
    /*margin-top: 16px;*/
    margin-bottom: 16px;

    .van-search {
      padding: 0px;
      flex: 1;
    }

    :deep(.van-search__content) {
      height: 100%;
      align-items: center;

      .van-field__left-icon {
        margin-right: 10px;
      }
    }

    :deep(.van-field__control::placeholder) {
      font-size: 14px;
      line-height: normal;
      font-weight: normal;
      color: #999;
    }

    :deep(.van-dropdown-menu__bar) {
      height: 44px;
      width: 86px;
      border-radius: 8px;
      border: 1px solid #e5e5e5;
      box-shadow: none;
    }

    :deep(.van-dropdown-menu__title) {
      padding: 0px;
      display: flex;
      align-items: center;
      column-gap: 10px;
    }

    :deep(.van-ellipsis) {
      font-size: 14px;
      line-height: normal;
      font-weight: normal;
      color: #333;
    }

    :deep(.van-dropdown-menu__title:after) {
      content: url("list-refresh-load/down.svg");
      border: none;
      transform: none;
      position: static;
      margin-top: 0px;
      width: 16px;
      height: 16px;
    }

    :deep(.van-popup) {
      background: #f6f8ff;
      padding: 20px;
      display: flex;
      flex-direction: column;
      row-gap: 20px;
    }
  }

  &__container {
    flex: 1;
  }
}

.sift-btn {
  display: flex;
  justify-content: end;
  column-gap: 10px;
  margin-top: 30px;

  .van-button {
    height: 35px;
    width: 70px;
  }
}

.container {
  &__empty {
    height: 100%;
  }
}

:deep(.van-pull-refresh) {
  height: 100%;

  /* 不能！！通过来div判断是否到底部需要执行load */
  /*.van-list__placeholder {
    display: none;
  }*/
}

:deep(.van-list) {
  display: flex;
  flex-direction: column;
  row-gap: 16px;
}
</style>
